package com.yunxi.core.util;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class MyZipUtils {
   public MyZipUtils() {
   }

   public void doCompress(String srcFile, String zipFile) throws IOException {
      doCompress(new File(srcFile), new File(zipFile));
   }

   /**
    * 文件压缩
    *
    * @param srcFile 目录或者单个文件
    * @param zipFile 压缩后的ZIP文件
    */
   public void doCompress(File srcFile, File zipFile) throws IOException {
      ZipOutputStream out = null;
      try {
         out = new ZipOutputStream(new FileOutputStream(zipFile));
         doCompress(srcFile, out);
      } catch (Exception e) {
         throw e;
      } finally {
         out.close();//记得关闭资源
      }
   }

   public void doCompress(String filelName, ZipOutputStream out) throws IOException {
      doCompress(new File(filelName), out);
   }

   public void doCompress(File file, ZipOutputStream out) throws IOException {
      doCompress(file, out, "");
   }

   public static void doCompress(File inFile, ZipOutputStream out, String dir) throws IOException {
      if (inFile.isDirectory()) {
         File[] files = inFile.listFiles();
         if (files != null && files.length > 0) {
            for (File file : files) {
               String name = inFile.getName();
               if (!"".equals(dir)) {
                  name = dir + "/" + name;
               }
               MyZipUtils.doCompress(file, out, name);
            }
         }
      } else {
         MyZipUtils.doZip(inFile, out, dir);
      }
   }

   public static void doZip(File inFile, ZipOutputStream out, String dir) throws IOException {
      String entryName = null;
      if (!"".equals(dir)) {
         entryName = dir + "/" + inFile.getName();
      } else {
         entryName = inFile.getName();
      }
      ZipEntry entry = new ZipEntry(entryName);
      out.putNextEntry(entry);

      int len = 0;
      byte[] buffer = new byte[1024];
      FileInputStream fis = new FileInputStream(inFile);
      while ((len = fis.read(buffer)) > 0) {
         out.write(buffer, 0, len);
         out.flush();
      }
      out.closeEntry();
      fis.close();
   }

   //.split("WEB-INF")[0]+ "upload/"
   private String filePath;

   {
      try {
         filePath = URLDecoder.decode(MyZipUtils.class.getResource("/").getPath(), "utf-8");
      } catch (UnsupportedEncodingException e) {
         e.printStackTrace();
      }
   }


   public static void main(String[] args) throws IOException {
//      doCompress("C:/Users/Lzk/Desktop/4444", "C:/Users/Lzk/Desktop/6666.zip");
      System.out.println(System.currentTimeMillis());
//      System.out.println(filePath);

//      String property = System.getProperty("user.dir");
//      System.out.println(property);

//      try {//异常处理
//         //如果Qiju_Li文件夹下没有Qiju_Li.txt就会创建该文件
//         BufferedWriter bw = new BufferedWriter(new FileWriter("C:/Users/Lzk/Desktop/aaa/2323.txt"));
//         bw.write("Hello I/O!");//在创建好的文件中写入"Hello I/O"
//         bw.close();//一定要关闭文件
//      } catch (IOException e) {
//         e.printStackTrace();
//      }

//      delFile(file);

   }

   //删除文件夹及内容
   public boolean delFile(File file) {
      if (!file.exists()) {
         return false;
      }
      if (file.isDirectory()) {
         File[] files = file.listFiles();
         for (File f : files) {
            delFile(f);
         }
      }
      return file.delete();
   }

   /**
    * 把文件打成压缩包并输出到客户端浏览器中
    */
   public static void downloadZipFiles(HttpServletResponse response, List<String> srcFiles, String zipFileName) {
      try {
         response.reset(); // 重点突出
         response.setCharacterEncoding("UTF-8"); // 重点突出
         response.setContentType("application/x-msdownload"); // 不同类型的文件对应不同的MIME类型 // 重点突出
         // 对文件名进行编码处理中文问题
         zipFileName = new String(zipFileName.getBytes(), StandardCharsets.UTF_8);
         // inline在浏览器中直接显示，不提示用户下载
         // attachment弹出对话框，提示用户进行下载保存本地
         // 默认为inline方式
         response.setHeader("Content-Disposition", "attachment;filename=" + zipFileName);

         // --设置成这样可以不用保存在本地，再输出， 通过response流输出,直接输出到客户端浏览器中。
         ZipOutputStream zos = new ZipOutputStream(response.getOutputStream());
         zipFile(srcFiles, zos);
      } catch (IOException e) {
         e.printStackTrace();
      }
   }


   /**
    * 压缩文件
    *
    * @param filePaths 需要压缩的文件路径集合
    * @throws IOException
    */
   private static void zipFile(List<String> filePaths, ZipOutputStream zos) {
      //设置读取数据缓存大小
      byte[] buffer = new byte[4096];
      try {
         //循环读取文件路径集合，获取每一个文件的路径
         for (String filePath : filePaths) {
            File inputFile = new File(filePath);
            //判断文件是否存在
            if (inputFile.exists()) {
               //判断是否属于文件，还是文件夹
               if (inputFile.isFile()) {
                  //创建输入流读取文件
                  BufferedInputStream bis = new BufferedInputStream(new FileInputStream(inputFile));
                  //将文件写入zip内，即将文件进行打包
                  zos.putNextEntry(new ZipEntry(inputFile.getName()));
                  //写入文件的方法，同上
                  int size = 0;
                  //设置读取数据缓存大小
                  while ((size = bis.read(buffer)) > 0) {
                     zos.write(buffer, 0, size);
                  }
                  //关闭输入输出流
                  zos.closeEntry();
                  bis.close();
               } else {  //如果是文件夹，则使用穷举的方法获取文件，写入zip
                  File[] files = inputFile.listFiles();
                  List<String> filePathsTem = new ArrayList<String>();
                  for (File fileTem : files) {
                     filePathsTem.add(fileTem.toString());
                  }
                  zipFile(filePathsTem, zos);
               }
            }
         }
      } catch (IOException e) {
         e.printStackTrace();
      } finally {
         if (null != zos) {
            try {
               zos.close();
            } catch (IOException e) {
               e.printStackTrace();
            }
         }
      }
   }

   public void downloadZipFile(HttpServletResponse response, String zip, String zipFileName) throws IOException {
      response.reset(); // 重点突出
      response.setCharacterEncoding("UTF-8"); // 重点突出
      response.setContentType("application/x-msdownload"); // 不同类型的文件对应不同的MIME类型 // 重点突出
      // 对文件名进行编码处理中文问题
      zipFileName = new String(zipFileName.getBytes(), StandardCharsets.UTF_8);
      // inline在浏览器中直接显示，不提示用户下载
      // attachment弹出对话框，提示用户进行下载保存本地
      // 默认为inline方式
      response.setHeader("Content-Disposition", "attachment;filename=" + zipFileName);
      response.setHeader("Access-Control-Allow-Origin","*");

      File inputFile = new File(zip);
      ServletOutputStream outs = response.getOutputStream();
      ZipOutputStream zos = new ZipOutputStream(outs);
      //设置读取数据缓存大小
      byte[] buffer = new byte[4096];
      try {
         if (inputFile.exists()) {
            //判断是否属于文件，还是文件夹
            if (inputFile.isFile()) {
               //创建输入流读取文件
               BufferedInputStream bis = new BufferedInputStream(new FileInputStream(inputFile));
               //将文件写入zip内，即将文件进行打包
//               zos.putNextEntry(new ZipEntry(inputFile.getName()));
               //写入文件的方法，同上
               int size = 0;
               //设置读取数据缓存大小
               while ((size = bis.read(buffer)) > 0) {
                  outs.write(buffer, 0, size);
               }
               //关闭输入输出流
               outs.close();
               zos.closeEntry();
               bis.close();
            }else {  //如果是文件夹，则使用穷举的方法获取文件，写入zip
               File[] files = inputFile.listFiles();
               List<String> filePathsTem = new ArrayList<String>();
               for (File fileTem : files) {
                  filePathsTem.add(fileTem.toString());
               }
               zipFile(filePathsTem, zos);
            }
         }
      } catch (IOException e) {
         e.printStackTrace();
      } finally {
         if (null != zos) {
            try {
               zos.close();
            } catch (IOException e) {
               e.printStackTrace();
            }
         }
      }
   }
}
